package com.ssy.lingxi.pay.callback;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.dto.request.CallbackCommunicationPayVO;
import com.ssy.lingxi.feign.MemberSettlementControllerFeign;
import com.ssy.lingxi.order.api.feign.OrderFeignService;
import com.ssy.lingxi.order.api.model.vo.request.OrderPayCallbackFeignVO;
import com.ssy.lingxi.pay.api.common.ServiceTypeEnum;
import com.ssy.lingxi.pay.api.common.allInPay.AllInPayResultEnum;
import com.ssy.lingxi.pay.entity.allInPay.AllInPay;
import com.ssy.lingxi.pay.entity.allInPay.AllInPayAttach;
import com.ssy.lingxi.pay.model.assetAccount.AllInPayAttachInfo;
import com.ssy.lingxi.pay.repository.allInPay.AllInPayAttachRepository;
import com.ssy.lingxi.pay.repository.allInPay.AllInPayRepository;
import com.ssy.lingxi.pay.service.ICreditService;
import com.ssy.lingxi.pay.service.IPayCacheService;
import com.ssy.lingxi.pay.service.assetAccount.IMemberAssetAccountService;
import com.ssy.lingxi.pay.service.eAccount.IEAccountTradeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;

/**
 * 通联支付回调接口
 *
 * @author lqa
 * @version 2.0.0
 * @date 2021/11/29
 */
@RestController
@RequestMapping("/pay/allInPay/notify")
public class AllInPayNotifyController {
    private static final Logger logger = LoggerFactory.getLogger(AllInPayNotifyController.class);
    @Resource
    private AllInPayRepository allInPayRepository;
    @Resource
    private AllInPayAttachRepository allInPayAttachRepository;
    @Resource
    private IPayCacheService payCacheService;
    @Resource
    private IMemberAssetAccountService memberAssetAccountService;
    @Resource
    private OrderFeignService orderFeignService;
    @Resource
    private ICreditService creditService;
    @Resource
    private IEAccountTradeService eAccountTradeService;
    @Resource
    private MemberSettlementControllerFeign settlementControllerFeign;

    /**
     * 会员签约结果回调地址
     *
     * @param param 操作结果
     */
    @RequestMapping(value = "/signContract", method = RequestMethod.POST)
    @ResponseBody
    public void signContract(@RequestParam Map<String, Object> param) {
        logger.info("会员电子协议签约返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            if (AllInPayResultEnum.SUCCESS.getMsg().equals(status)) {
                JSONObject returnValue = resp.getJSONObject("returnValue");
                //成功就保存数据
                String bizUserId = returnValue.getString("bizUserId");
                AllInPay allInPay = allInPayRepository.findByBizUserId(bizUserId);
                allInPay = allInPay != null ? allInPay : new AllInPay();
                allInPay.setBizUserId(bizUserId);
                allInPay.setContractNo(resp.getString("ContractNo"));
                allInPay.setIsSign(1);
                allInPayRepository.saveAndFlush(allInPay);
            }
        }
        logger.info("会员电子协议签约返回结果->{}", "result");
    }


    /**
     * 影印件核对结果异步通知地址
     *
     * @param param 操作结果
     */
    @RequestMapping(value = "/idCardCollect", method = RequestMethod.POST)
    @ResponseBody
    public void idCardCollect(@RequestParam Map<String, Object> param) {
        logger.info("影印件核对结果异步通知返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            if(AllInPayResultEnum.SUCCESS.getMsg().equals(status)){
                JSONObject returnValue = resp.getJSONObject("returnValue");
                String bizUserId = returnValue.getString("bizUserId");
                Long ocrRegNumComparisonResult = returnValue.getLong("ocrRegnumComparisonResult");//OCR 识别与企业工商认证信息 是否一致 0-否1-是该字段与“OCR 识别与企业法 人实名信息是否一致”字段有 一方发生变更即返值 若营业执照未进行识别该字段不返
                Long ocrIdCardComparisonResult = returnValue.getLong("ocrIdcardComparisonResult");//OCR 识别与企业法人实名信息 是否一致 0-否1-是该字段与“OCR 识别与企业工 商认证信息是否一致”字段有 一方发生变更即返值 若法人身份证未进行识别该字段不返
                AllInPayAttach allInPayAttach = allInPayAttachRepository.findByBizUserId(bizUserId);
                allInPayAttach = allInPayAttach != null ? allInPayAttach : new AllInPayAttach();
                allInPayAttach.setOcrRegNumComparisonResult(ocrRegNumComparisonResult.intValue());
                allInPayAttach.setOcrIdCardComparisonResult(ocrIdCardComparisonResult.intValue());
                allInPayAttachRepository.saveAndFlush(allInPayAttach);
            }
        }
    }

    /**
     * 通联支付-设置支付密码【密码验证版】回调信息
     */
    @RequestMapping(value = "/setPayPwd", method = RequestMethod.POST)
    @ResponseBody
    public void setPayPwd(@RequestParam Map<String, Object> param) {
        logger.info("联支付-设置支付密码【密码验证版】回调信息返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            JSONObject returnValue = resp.getJSONObject("returnValue");
            if (AllInPayResultEnum.SUCCESS.getMsg().equals(status)) {
                AllInPayAttach payAttach = allInPayAttachRepository.findByBizUserId(returnValue.getString("bizUserId"));
                payAttach.setIsSetPayPwd(1);
                allInPayAttachRepository.saveAndFlush(payAttach);
            }
        }
    }

    /**
     * 通联支付-修改支付密码【密码验证版】回调信息
     */
    @RequestMapping(value = "/updatePayPwd", method = RequestMethod.POST)
    @ResponseBody
    public void updatePayPwd(@RequestParam Map<String, Object> param) {
        logger.info("联支付-修改支付密码【密码验证版】回调信息返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            JSONObject resp = JSONObject.parseObject(rps);
            JSONObject returnValue = resp.getJSONObject("returnValue");
            //TODO:待添加修改成功标识
        }
    }

    /**
     * 通联支付-重置支付密码【密码验证版】回调信息
     */
    @RequestMapping(value = "/resetPayPwd", method = RequestMethod.POST)
    @ResponseBody
    public void resetPayPwd(@RequestParam Map<String, Object> param) {
        logger.info("联支付-重置支付密码【密码验证版】回调信息返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            logger.info("------------通联支付回调通知:rps--------------:{}", rps);
            JSONObject resp = JSONObject.parseObject(rps);
            JSONObject returnValue = resp.getJSONObject("returnValue");
            //TODO:待重置修改成功标识
        }
    }

    /**
     * 支付通知接口
     * 1. 首先记录支付宝流水
     * 2. 进行业务操作
     */
    @RequestMapping(value = "/consumeApply", method = RequestMethod.POST)
    @ResponseBody
    public void notify(@RequestParam Map<String, Object> param) {
        logger.info("------------通联支付回调通知--------------:{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            JSONObject returnValue = resp.getJSONObject("returnValue");
            String buyerBizUserId = returnValue.getString("buyerBizUserId");
            String amount = returnValue.getString("amount");
            String trade_no = returnValue.getString("orderNo");
            String payDatetime = returnValue.getString("payDatetime");
            String out_trade_no = returnValue.getString("bizOrderNo");


            String attachStr = returnValue.getString("extendInfo");
            AllInPayAttachInfo attachInfo = payCacheService.deserializeObject(attachStr, AllInPayAttachInfo.class);
            //解析附加信息
            String serviceType = attachInfo.getServiceType();       //服务类型p
            String attach = attachInfo.getAttach();                 //附加信息

            if (AllInPayResultEnum.SUCCESS.getMsg().equals(status)) {
                //回调业务方法
                if (ServiceTypeEnum.Pay_Credit.getCode().equals(serviceType)) {
                    creditService.confirmRepaySucceed(out_trade_no, trade_no);
                    logger.info(ServiceTypeEnum.Pay_Credit.getMessage() + ":==========订单号：" + out_trade_no + "通知成功");
                } else if (ServiceTypeEnum.Order_Pay.getCode().equals(serviceType)) {
                    OrderPayCallbackFeignVO orderPayCallbackFeignVO = new OrderPayCallbackFeignVO();
                    orderPayCallbackFeignVO.setTradeNo(out_trade_no);
                    orderPayCallbackFeignVO.setAttach(attach);
                    orderPayCallbackFeignVO.setPaySuccess(true);
                    Wrapper<Void> orderCallbackResult = orderFeignService.orderPayCallback(orderPayCallbackFeignVO);
                    logger.info(ServiceTypeEnum.Order_Pay.getMessage() + ":==========订单号：" + out_trade_no + " attach：" + attach + " , 支付成功通知结果" + orderCallbackResult.getMessage());
                } else if (ServiceTypeEnum.SETTLEMENT_Pay.getCode().equals(serviceType)) {
                    CallbackCommunicationPayVO request = new CallbackCommunicationPayVO();
                    request.setTradeNo(out_trade_no);
                    request.setToken(attach);
                    logger.info("调用前" +ServiceTypeEnum.Order_Pay.getMessage() +":" + JSONUtil.toJsonStr(request));
                    Wrapper<Boolean> orderCallbackResult = settlementControllerFeign.confirmCommunicationPay(request);
                    logger.info(ServiceTypeEnum.Order_Pay.getMessage() + ":==========订单号：" + out_trade_no + " attach：" + attach + " , 支付成功通知结果" + orderCallbackResult.getMessage());

                } else {
                    logger.error("==========订单号：" + out_trade_no + "通知失败，未找到对应的服务");
                }
            } else {
                if (ServiceTypeEnum.Order_Pay.getCode().equals(serviceType)) {
                    OrderPayCallbackFeignVO orderPayCallbackFeignVO = new OrderPayCallbackFeignVO();
                    orderPayCallbackFeignVO.setTradeNo(out_trade_no);
                    orderPayCallbackFeignVO.setAttach(attach);
                    orderPayCallbackFeignVO.setPaySuccess(false);
                    Wrapper<Void> orderCallbackResult = orderFeignService.orderPayCallback(orderPayCallbackFeignVO);
                    logger.info(ServiceTypeEnum.Order_Pay.getMessage() + ":==========订单号：" + out_trade_no + " attach：" + attach + " , 支付失败通知结果" + orderCallbackResult.getMessage());
                }
            }
        }
    }


    /**
     * 代收支付通知接口
     * 1. 首先记录支付宝流水
     * 2. 进行业务操作
     */
    @RequestMapping(value = "/agentCollectApply", method = RequestMethod.POST)
    @ResponseBody
    public void agentCollectApply(@RequestParam Map<String, Object> param) {
        logger.info("------------通联支付回调通知--------------:{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            JSONObject returnValue = resp.getJSONObject("returnValue");

            String trade_no = returnValue.getString("orderNo");
            String payDatetime = returnValue.getString("payDatetime");
            String out_trade_no = returnValue.getString("bizOrderNo");
            String attachStr = returnValue.getString("extendInfo");
            AllInPayAttachInfo attachInfo = payCacheService.deserializeObject(attachStr, AllInPayAttachInfo.class);
            //解析附加信息
          // Integer payType = attachInfo.getPayType();              //支付方式
          // String bizUserId = attachInfo.getBizUserId();               //会员id 收款人
            String serviceType = attachInfo.getServiceType();       //服务类型p
            String attach = attachInfo.getAttach();                 //附加信息
            //通联支付交易记录会在通联平台自己新增
            //判断是否支付成功(待测试)
            if (AllInPayResultEnum.SUCCESS.getMsg().equals(status)) {

                //回调业务方法
                if (ServiceTypeEnum.Pay_Recharge.getCode().equals(serviceType)) {
                    memberAssetAccountService.payNotify(out_trade_no, trade_no);
                    logger.info(ServiceTypeEnum.Pay_Recharge.getMessage() + ":==========订单号：" + out_trade_no + "通知成功");
                } else if (ServiceTypeEnum.Pay_Credit.getCode().equals(serviceType)) {
                    creditService.confirmRepaySucceed(out_trade_no, trade_no);
                    logger.info(ServiceTypeEnum.Pay_Credit.getMessage() + ":==========订单号：" + out_trade_no + "通知成功");
                } else if (ServiceTypeEnum.Order_Pay.getCode().equals(serviceType)) {
                    OrderPayCallbackFeignVO orderPayCallbackFeignVO = new OrderPayCallbackFeignVO();
                    orderPayCallbackFeignVO.setTradeNo(out_trade_no);
                    orderPayCallbackFeignVO.setAttach(attach);
                    orderPayCallbackFeignVO.setPaySuccess(true);
                    Wrapper<Void> orderCallbackResult = orderFeignService.orderPayCallback(orderPayCallbackFeignVO);
                    logger.info(ServiceTypeEnum.Order_Pay.getMessage() + ":==========订单号：" + out_trade_no + " attach：" + attach + " , 支付成功通知结果" + orderCallbackResult.getMessage());
                } else {
                    logger.error("==========订单号：" + out_trade_no + "通知失败，未找到对应的服务");
                }
            } else {
                if (ServiceTypeEnum.Order_Pay.getCode().equals(serviceType)) {
                    OrderPayCallbackFeignVO orderPayCallbackFeignVO = new OrderPayCallbackFeignVO();
                    orderPayCallbackFeignVO.setTradeNo(out_trade_no);
                    orderPayCallbackFeignVO.setAttach(attach);
                    orderPayCallbackFeignVO.setPaySuccess(false);
                    Wrapper<Void> orderCallbackResult = orderFeignService.orderPayCallback(orderPayCallbackFeignVO);
                    logger.info(ServiceTypeEnum.Order_Pay.getMessage() + ":==========订单号：" + out_trade_no + " attach：" + attach + " , 支付失败通知结果" + orderCallbackResult.getMessage());
                }
            }
        }
    }

    /**
     * 通联支付-单笔托管代付（标准版）(付款到账户余额)回调信息
     */
    @RequestMapping(value = "/signalAgentPay", method = RequestMethod.POST)
    @ResponseBody
    public void signalAgentPay(@RequestParam Map<String, Object> param) {
        logger.info("通联支付-单笔托管代付（标准版）(付款到账户余额)回调信息返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            JSONObject returnValue = resp.getJSONObject("returnValue");
        }
    }

    /**
     * 通联支付-批量托管代付（标准版）(付款到账户余额)回调信息
     */
    @RequestMapping(value = "/batchAgentPay", method = RequestMethod.POST)
    @ResponseBody
    public void batchAgentPay(@RequestParam Map<String, Object> param) {
        logger.info("通联支付-批量托管代付（标准版）(付款到账户余额)回调信息返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            JSONObject returnValue = resp.getJSONObject("returnValue");
        }
    }

    /**
     * 通联支付-退款申请
     */
    @RequestMapping(value = "/refund", method = RequestMethod.POST)
    @ResponseBody
    public void refund(@RequestParam Map<String, Object> param) {
        logger.info("通联支付-退款申请回调信息返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            logger.info("------------通联支付回调通知:rps--------------:{}", rps);
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            JSONObject returnValue = resp.getJSONObject("returnValue");
        }
    }

    /**
     * 通联支付-充值申请
     */
    @RequestMapping(value = "/depositApply", method = RequestMethod.POST)
    @ResponseBody
    public void depositApply(@RequestParam Map<String, Object> param) {
        logger.info("通联支付-充值申请回调信息返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            logger.info("------------通联支付回调通知:rps--------------:{}", rps);
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            JSONObject returnValue = resp.getJSONObject("returnValue");
            String payInterfaceOutTradeNo = returnValue.getString("payInterfaceOutTradeNo");//
            String buyerBizUserId = returnValue.getString("buyerBizUserId");//购买者
            Long amount = returnValue.getLong("amount");//充值金额,单位 分
            Long channelFee = returnValue.getLong("channelFee");//手续费,单位 分
            String channelPaytime = returnValue.getString("channelPaytime");
            String payDatetime = returnValue.getString("payDatetime");//支付时间
            String payInterfacetrxcode = returnValue.getString("payInterfacetrxcode");
            String orderNo = returnValue.getString("orderNo");//支付单号
            String cusId = returnValue.getString("cusid");
            String bizOrderNo = returnValue.getString("bizOrderNo");//这个是我们充值时候传过去的订单号
            String acct = returnValue.getString("acct");

            if (AllInPayResultEnum.SUCCESS.getMsg().equals(status)) {
                logger.info("------------通联支付回调通知:更新交易记录bizOrderNo--------------:{}", bizOrderNo);
                logger.info("------------通联支付回调通知:更新交易记录orderNo--------------:{}", orderNo);
                eAccountTradeService.rechargeNotify(bizOrderNo, orderNo);
            }
        }
    }

    /**
     * 通联支付-提现申请
     */
    @RequestMapping(value = "/withdrawApply", method = RequestMethod.POST)
    @ResponseBody
    public void withdrawApply(@RequestParam Map<String, Object> param) {
        logger.info("通联支付-提现申请回调信息返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            logger.info("------------通联支付回调通知:rps--------------:{}", rps);
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            JSONObject returnValue = resp.getJSONObject("returnValue");
            String buyerBizUserId = returnValue.getString("buyerBizUserId");//提现者
            String amount = returnValue.getString("amount");//提现金额 单位:分
            String orderNo = returnValue.getString("orderNo");
            String extendInfo = returnValue.getString("extendInfo");
            String payDatetime = returnValue.getString("status");
            String acct = returnValue.getString("acct");
            String bizOrderNo = returnValue.getString("bizOrderNo");

            if(AllInPayResultEnum.SUCCESS.getMsg().equals(status)){
                logger.info("------------通联支付回调通知:更新交易记录bizOrderNo--------------:{}", bizOrderNo);
                logger.info("------------通联支付回调通知:更新交易记录orderNo--------------:{}", orderNo);
                eAccountTradeService.cashOutNotify(bizOrderNo, orderNo);
            }
        }
    }

    /**
     * 通联支付-订单分账退款申请
     */
    @RequestMapping(value = "/orderSplitRefund", method = RequestMethod.POST)
    @ResponseBody
    public void orderSplitRefund(@RequestParam Map<String, Object> param) {
        logger.info("通联支付-订单分账退款申请回调信息返回结果->{}", param);
        if (!Objects.isNull(param)) {
            String rps = param.get("rps").toString();
            logger.info("------------通联支付回调通知:rps--------------:{}", rps);
            JSONObject resp = JSONObject.parseObject(rps);
            String status = resp.getString("status");
            JSONObject returnValue = resp.getJSONObject("returnValue");
            String buyerBizUserId = returnValue.getString("buyerBizUserId");//提现者
            String amount = returnValue.getString("amount");//提现金额 单位:分
            String orderNo = returnValue.getString("orderNo");
            String extendInfo = returnValue.getString("extendInfo");
            String payDatetime = returnValue.getString("status");
            String acct = returnValue.getString("acct");
            String bizOrderNo = returnValue.getString("bizOrderNo");
        }
    }
}
